:- module(var_name).
:- export get_a_var_name / 2.
:- export get_var_name / 2.
:- export set_var_name_counter / 2.
:- export set_var_name / 2.
:- comment(summary, "Allows variables to be given stable and unique names.").
:- comment(desc, html("    <P>\n    The var_name library is used to allow variables to be given unique and\n    stable names. These names are printed whenever the variable is printed.\n    The main novel feature is that the name is unique at any time, and that\n    this name is stable in that it would not change between runs of the same\n    program.\n    </P><P>\n    These variable names are intended solely for purposes of debugging\n    and visualisation of a program execution. Any use of this feature\n    in the actual program logic or algorithm is strongly discouraged.\n    </P>\n")).
:- comment(get_var_name / 2, [summary : "Retrieve the name given to a variable via set_var_name/2", args : ["Var" : "Named variable", "Name" : "Variable, will be bound to a string"], amode : get_var_name(?, -), fail_if : "Var is not a variable or has not been named via set_var_name/2", desc : html("\t<P>\n\t  Used to retrieve the unique name that was given to a variable via\n\t  the set_var_name/2 predicate. This name is always of the form\n\t  BaseName#N, where BaseName is the base name that was specified in\n\t  set_var_name/2, and N is an integer.\n\t</P><P>\n\t  These variable names are intended solely for purposes of debugging\n\t  and visualisation of a program execution. Any use of this feature\n\t  in the actual program logic or algorithm is strongly discouraged.\n\t</P>\n\t"), see_also : [set_var_name / 2]]).
:- comment(set_var_name / 2, [summary : "Give a unique name to each variable in Vars based on BaseName and a counter.", args : ["Vars" : "Variable(s) to be named (Prolog term)", "BaseName" : "BaseName of variable (atom or string)"], amode : set_var_name(?, ++), desc : html("    <P>\n      Give unique and stable names to the variables in Vars. The names have\n      the format BaseName#N where N is the value of a counter, which is\n      incremented each time a variable is named by <TT>set_var_name/2</TT>. \n      Thus all such named variables are given a unique name. This name is \n      printed wherever the `source name' of a variable would otherwise\n      be printed.  Wherever the system would normally add an arbitrary\n      number to the printed name (e.g. the 'V' option in printf, or the\n      variables(full) option in write_term printing Name_Number), this\n      is not done with named variables.\n\n    </P><P>\n      BaseName must begin with a capital letter, thus the name looks like a\n      normal ECLiPSe variable name, but they can be recognised as named\n      variables because a normal variable name cannot contain the '#'\n      symbol.  Each BaseName has its own counter, which by default starts\n      at 0 and is incremented each time a variable with that BaseName is\n      named. The default starting value can be changed by\n      set_var_name_counter/2 before any calls to set_var_name/2 with the\n      BaseName.  Note that the counter value is backtrackable.\n      \n    </P><P>\n      Vars is usually a variable, or a list of variables that the user would\n      like to have the same base name BaseName. Vars is traversed in the usual\n      depth-first left-to-right manner and the variables found numbered \n      consecutively with the same base name BaseName. \n\n    </P><P>\n      The main feature of this name is that the name is unique and stable.\n      The name is unique in that at any given time during an ECLiPSe\n      execution, the combination of the BaseName and counter can only refer\n      to one variable. The name is stable in that this unique name would\n      not change between runs of the program or running the program on\n      different platforms. Thus, this allows the user to for example\n      uniquely identify a variable between a normal and a debugging run of\n      the program.\n\n    </P><P>\n      The predicate fails if any variables in Vars has already been given a\n      name. In particular, this means that all variables in Vars should\n      occur only once. When two named variable are unified, the older name\n      is retained, as in existing rules for variable names.\n\n   </P><P>\n      The variable name is implemented as an attribute. Thus all named\n      variables become attributed variables, which is recognised by\n      ECLiPSe and treated specially when a named variable is printed. It is\n      possible to construct a named variable by directly creating the\n      attribute, either by reading in a previous named variable written\n      using writeq, or by the user explicitly constructing the\n      attribute. In such cases, the name is not recorded by the system and\n      may not be unique in that set_var_name/2 would not take it into\n      account in naming new variables.\n\n"), fail_if : "Var contain variable(s) that have already been named by set_var_name/2.", exceptions : [5 : "BaseName is not an atom or string.", 6 : "BaseName does not begin with a capital letter."], resat : no, see_also : [get_var_name / 2, set_var_name_counter / 2], index : ["variable name", "naming variable", "stable and unique names"], eg : "\n[eclipse 1]: lib(var_name).\nvar_name.ecl compiled traceable 1308 bytes in 0.02 seconds\n\nYes (0.03s cpu)\n[eclipse 2]: \n\n\n[eclipse 3]: set_var_name(X, 'Myname'), set_var_name(Y, \"Myname\").\n\nX = Myname#0\nY = Myname#1\nYes (0.00s cpu)\n[eclipse 4]: set_var_name(X, 'Count'), writeln(X).\nCount#0\n\nX = Count#0\nYes (0.00s cpu)\n\n% name is backtrackable. Original source name printed in second branch\n[eclipse 5]: (set_var_name(X, 'Name') ; true), writeln(X), fail.       \nName#0\nX\n\nNo (0.00s cpu)\n\n% naming more than one variable at a time...\n[eclipse 10]: length(L,5), set_var_name(L, 'Start').\n\nL = [Start#0, Start#1, Start#2, Start#3, Start#4]\nYes (0.00s cpu)\n\n% counter is backtrackable\n[eclipse 11]: (set_var_name([X,Y], 'Name') ; set_var_name(Y, 'Name')), writeln(X-Y), fail.\nName#0 - Name#1\nX - Name#0\n\nNo (0.00s cpu)\n\n% each base name has its own counter\n[eclipse 12]: set_var_name(X, 'First'), set_var_name(Y, 'Second'), writeln(X-Y).\nFirst#0 - Second#0\n\nX = First#0\nY = Second#0\nYes (0.00s cpu)\n\n% older name is retained on unification\n[eclipse 9]:  set_var_name(X, 'First'), set_var_name(Y, 'Second'), X = Y, writeln(Y).\nFirst#0\n\nX = First#0\nY = First#0\nYes (0.00s cpu)\n\n[eclipse 10]: lib(fd), X::[1..5], set_var_name(X, 'Domain'), writeln(X).\nfd_domain.pl compiled traceable 22556 bytes in 0.04 seconds\nfd_arith.pl compiled traceable 72296 bytes in 0.13 seconds\nfd_util.pl compiled traceable 2128 bytes in 0.02 seconds\nfd_chip.pl compiled traceable 4720 bytes in 0.05 seconds\nfd_elipsys.pl compiled traceable 11036 bytes in 0.02 seconds\nfd.pl      compiled traceable 17256 bytes in 0.29 seconds\nDomain#0{[1..5]}\n\nX = Domain#0{[1..5]}\nYes (0.29s cpu)\n\n% fails if variable already named\n[eclipse 7]: set_var_name(X, 'Name'), set_var_name(X, 'New').\n\nNo (0.00s cpu)\n\n% no number is attached to name when printed with 'V' option\n[eclipse 14]: set_var_name(X, 'Myname'), printf(\"%Vw%n%Vw%n\", [X,Y]).\nMyname#0\nY_177\n\nX = Myname#0\nY = Y\nYes (0.00s cpu)\n\n% writeq does not print the name\n[eclipse 15]: set_var_name(X, 'Myname'), writeq(X).\n_282{suspend : _285, var_name : vname(\"Myname\", 0)}\nX = Myname#0\nYes (0.00s cpu)\n\n[eclipse 12]: set_var_name(X, 123).\nout of range in set_var_name(X, 123)\nAbort\n[eclipse 13]: set_var_name(X, atomic).\nout of range in set_var_name(X, atomic)\nAbort\n[eclipse 14]: set_var_name(X, f(structure)).\ntype error in set_var_name(X, f(structure))\nAbort\n\n\n"]).
:- comment(set_var_name_counter / 2, [summary : "Set the initial value for the counter for variable name BaseName.", args : ["BaseName" : "A valid base-name (atom or string)", "Start" : "Start value for counter (integer)"], amode : set_var_name_counter(++, ++), desc : html("    <P>\n\tSet the initial counter value for a variable name BaseName that will\n        then be used in set_var_name/2, with Start as the initial value of \n        the counter. If BaseName already exists (i.e. variables have already\n        been named using BaseName), the predicate will fail.\n\n    </P><P>\n        It is expected that the main use of this predicate will be to change\n        the default counter start value from 0 to 1. However, no restrictions \n        are placed on what the start value may be.\n"), fail_if : "BaseName already exists.", exceptions : [5 : "BaseName is not an atom or string.", 5 : "Start is not an integer.", 6 : "BaseName does not begin with a capital letter."], resat : no, see_also : [set_var_name / 2]]).
